﻿using TaskManagerLib.MinimumWork;
using TaskManagerLib.Symbol;

namespace TaskManagerLib.ComplexWork;

public class ComplexWork: IComplexWork
{
    public int ProcessPoint { get; set; }
    public List<IMiniWork> MiniWorks { get; set; } = new();
    public void AddMiniWork(IMiniWork? work)
    {
        if (work == null) return;
        if (!MiniWorks.Contains(work))
        {
            MiniWorks.Add(work);
        }
    }

    public ComplexWork(CancellationTokenSource source)
    {
        CancellationTokenSource = source;
    }

    public void AddRangeMiniWork(IEnumerable<MiniWork> works)
    {
        foreach (var miniWork in works)
        {
            AddMiniWork(miniWork);
        }
    }

    public void RemoveRangeMiniWork(IEnumerable<MiniWork> works)
    {
        foreach (var miniWork in works)
        {
            RemoveMiniWork(miniWork);
        }
    }

    public void RemoveMiniWork(IMiniWork? work)
    {
        if (work == null) return;
        if (MiniWorks.Contains(work))
        {
            MiniWorks.Remove(work);
        }
    }

    public long WorkId { get; set; }
    public double Progress { get; set; }
    public ProgressDelegate? Notification { get; set; }
    public WorkStatus? Status { get; set; }

    public CancellationTokenSource? CancellationTokenSource
    {
        get;
        set;
    }
    public void Pause()
    {
        Status = WorkStatus.Paused;
        CancellationTokenSource?.Cancel();
    }

    public bool IsFinished()
    {
        return MiniWorks.All(miniWork => miniWork.IsFinished());
    }

    public void UpdateTokenSource(CancellationTokenSource source)
    {
        CancellationTokenSource = source;
    }

    // 直接执行，
    public void Start()
    {
        CalculateProgress();
        Notice($"任务 {MiniWorks.Count(mini => mini.IsFinished())}/{MiniWorks.Count},进度{Progress}");
        foreach (var miniWork in MiniWorks.Where(mini=>mini.IsFinished()==false))
        {
            CalculateProgress();
            Notice($"正在查看任务{miniWork.WorkId}的状态，当前进度{Progress:F2}");
            switch (miniWork.Status)
            {
                case WorkStatus.Ready:
                    Notice($"{miniWork.WorkId}的状态为就绪，准备执行，当前进度{Progress:F2}");
                    miniWork.Start();
                    break;
                case WorkStatus.Except or WorkStatus.Paused:
                    Notice($"{miniWork.WorkId}的状态为异常或者暂停，准备恢复执行，当前进度{Progress:F2}");
                    miniWork.Resume(CancellationTokenSource);
                    miniWork.Start();
                    break;
                case WorkStatus.Running or WorkStatus.Finish:
                    Notice($"{miniWork.WorkId}的状态为完成或者正在执行，当前进度{Progress:F2}");
                    continue;
                case null:
                    miniWork.Build();
                    miniWork.Start();
                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }
        }
    }

    private void CalculateProgress()
    {
        Progress = 1.0* MiniWorks.Count(mini => mini.IsFinished()) / MiniWorks.Count;
    }
    // 按照顺序执行，异步阻塞每一个任务
    public async Task StartAndBlockAsync()
    {
        CalculateProgress();
        Notice($"任务执行 {MiniWorks.Count(mini => mini.IsFinished())}/{MiniWorks.Count},进度{Progress}");
        foreach (var miniWork in MiniWorks.Where(mini=>mini.IsFinished()==false))
        {
            CalculateProgress();
            Notice($"正在查看任务{miniWork.WorkId}的状态，当前进度{Progress:F2}");
            switch (miniWork.Status)
            {
                case WorkStatus.Ready:
                    Notice($"{miniWork.WorkId}的状态为就绪，准备执行，当前进度{Progress:F2}");
                    await miniWork.StartAndBlockAsync();
                    break;
                case WorkStatus.Except or WorkStatus.Paused:
                    miniWork.Resume(CancellationTokenSource);
                    Notice($"{miniWork.WorkId}的状态为异常或者暂停，准备恢复执行，当前进度{Progress:F2}");
                    await miniWork.StartAndBlockAsync();
                    break;
                case WorkStatus.Running or WorkStatus.Finish:
                    Notice($"{miniWork.WorkId}的状态为完成或者正在执行，当前进度{Progress:F2}");
                    continue;
                case null:
                    miniWork.Build();
                    await miniWork.StartAndBlockAsync();
                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }
            CalculateProgress();
            Notice($"任务{miniWork.WorkId}执行中断或完毕，当前进度{Progress:F2}");
        }
    }

    private void Notice(string message)
    {
        Notification?.Invoke(new ProgressNotification()
        {
            Progress = Progress,
            Message = message
        });
    }
}